<!--
 * @Author: 李金深 2896583081@qq.com
 * @Date: 2023-06-13 14:14:02
 * @LastEditors: 李金深 2896583081@qq.com
 * @LastEditTime: 2023-08-02 15:29:39
 * @FilePath: /com.huizhouyiren.web.d0101/src/components/upload/upload.vue
 * @Description: 文件上传组件
-->
<script setup>
import axios from "axios"
import { ref } from "vue"
import mitt from "@/mitt/index"
import viewPicture from "@/utils/previewImages"
const props = defineProps({
    type: { // 类型 avatar头像上传（单图片）  list 图片列表上传   button 按钮（按钮插槽）
        type: String,
        default: "avatar",
        validator(value) {
            return ['avatar', 'list', 'button'].includes(value)
        }
    },
    fileType: {// 上传的文件类型
        type: String,
        default: "image",
        validator(value) {
            return ['image', 'video', 'audio'].includes(value)
        }
    },
    modelValue: { // type为avatar时v-modal绑定的属性
        type: String,
        default: ""
    },
    list: {// 图片列表
        type: Array,
    },
    width: {
        type: String,
        // default: '6.25rem'
    },
    max: { // 上传的文件最大数量
        type: Number,
        default: 9
    },
    autoUpload: {
        type: Boolean,
        default: true
    },
    multiple: {
        type: Boolean,
        default: true
    }
})
const emit = defineEmits(['update:modelValue', 'update:list', 'uploadError', 'uploadSuccess', 'progressEvent'])

let fileInput = ref(null) // input

/**
 * @description: 选择图片
 * @return {*}
 */
const slectFile = function () {
    if (!props.autoUpload) {
        return
    }
    fileInput.value.click()
}

const controlledUpload = () => {
    fileInput.value.click()
}



let lang = localStorage.getItem('localeFlag') == 'true' ? 'en-us' : 'zh-cn'
let progress = ref(0)
let showPercent = ref(false)

/**
 * @description: input 选择文件后触发的事件
 * @param {*} e
 * @return {*}
 */
const changeFile = (e) => {
    let files = e.target.files;
    console.log(files)
    let formData = new FormData();
    files = Array.from(files); // files是类数组，需要先转为数组
    files.forEach((file) => {
        if (props.type == 'avatar') {
            formData.append("file", file);
        } else if (props.multiple) {
            formData.append("file[]", file);
        } else {
            formData.append("file", file);
        }
    });
    uploadFile(formData)
}

/**
 * @description: 文件上传
 * @param {*} formData
 * @return {*}
 */
const uploadFile = (formData) => {
    showPercent.value = true
    axios({
        url: `/api/file/upload?mime=${props.fileType == 'image' ? 'image' : 'video'}&source=message&lang=${lang}&type=${props.type == 'avatar' ? 1 : props.multiple ? 2 : 1}`,
        method: "post",
        headers: {
            Authorization: localStorage.getItem('USER_TOKEN'),
            "Content-Type": "mutilpart/form-data",
        },
        data: formData,
        onUploadProgress: (progressEvent) => {
            // console.log(progressEvent, progressEvent.loaded / progressEvent.total)
            //原生获取上传进度的事件
            // if (progressEvent.event.lengthComputable) {
            //     //属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
            //     //如果lengthComputable为false，就获取不到progressEvent.total和progressEvent.loaded
            // }
            progress.value = ((progressEvent.loaded / progressEvent.total) * 100).toFixed(0); //实时获取上传进度
            if (progress.value == 100) {
                showPercent.value = false
            }
            emit("progressEvent", progress.value)
        },
    })
        .then((res) => {
            if (res.data.code == 200) {
                if (props.type == 'avatar') {
                    emit("update:modelValue", res.data.data.src)
                    emit("uploadSuccess", { array: [res.data.data.src], type: props.fileType })
                } else if (props.type == 'button') {
                    let array = []
                    props.multiple ? array = res.data.data.src : array.push(res.data.data.src)
                    emit("uploadSuccess", { array, type: props.fileType })
                } else {
                    let dataList = [...props.list, ...res.data.data.src]
                    if (dataList.length >= props.max) {
                        dataList.splice(0, dataList.length - props.max)
                    }
                    emit("update:list", dataList)
                }
            } else {
                mitt.emit("messageTip", {
                    type: "erorr",
                    msg: res.data.msg
                })
                emit("uploadError")
            }
        })
        .catch(() => {
            showPercent.value = false
            emit("uploadError")
        });
}
/**
 * @description: 查看图片
 * @return {*}
 */
const viewPictureFunc = (index) => {
    viewPicture(index, props.list)
}
/**
 * @description: 移除图片
 * @return {*}
 */
const removePicture = (index) => {
    let list = [...props.list]
    list.splice(index, 1)
    emit("update:list", list)
}

let fileMap = {
    image: 'image/*',
    // video: "'video/*'",
    video: ".mp4",
    // audio: "audio/*",
    audio: '.mp3'
}


defineExpose({
    controlledUpload,
    uploadFile
})

</script>
<template>
    <div :style="{ width: type == 'button' ? '' : '100%' }">
        <input type="file" :multiple="type == 'avatar' ? false : multiple" :accept="fileMap[fileType]" ref="fileInput"
            style="display: none" @change="changeFile" />
        <div @click="slectFile" v-if="type == 'avatar'" style="position: relative;">
            <slot></slot>
            <div style="position: absolute;top: 0;right: 0;left: 0;bottom: 0;
                        background: rgba(0, 0, 0, .3);z-index: 99;display: flex;
                        justify-content: center;align-items: center;color: white;" v-if="showPercent">
                {{ progress }}
            </div>
        </div>
        <div v-if="type == 'button'" @click="slectFile">
            <slot name="button"></slot>
        </div>
        <div v-if="type == 'list'" style="display: flex;align-items: flex-end;flex-wrap: wrap;width: 100%;">
            <template v-if="props.fileType == 'image'">
                <div class="w-1/5 lg:w-1/6" v-for="(item, index) in props.list" :key="item" :style="{ width }" style="aspect-ratio: 1;
                    display: flex;align-items: center;justify-content: center;">
                    <div class="img_box"
                        style="border-radius: .25rem;width: 95%;height: 95%;overflow: hidden;display: flex;align-items: center;justify-content: center;position: relative;">
                        <img :src="item" alt="" style="width: 100%;height: 100%;object-fit: cover;">
                        <div class="mask"
                            style="position: absolute;top:0;left: 0;right: 0;bottom: 0;background: rgba(0,0,0,.3);display: flex;align-items: center;justify-content: center;">
                            <div style="display: flex;align-items: center;">
                                <img src="./images/view.png" alt="" @click="viewPictureFunc(index)"
                                    style="height: 1.4375rem;width: auto;cursor: pointer;">
                                <img src="./images/delete.png" alt="" @click="removePicture(index)"
                                    style="height: 1.4375rem;width: auto;margin-left: 1.125rem;cursor: pointer;">
                            </div>
                        </div>
                    </div>
                </div>
            </template>
            <template v-if="props.fileType == 'video'">
                <div v-for="item in props.list" :key="item" class="w-1/2" :style="{ width }" style="aspect-ratio: 16/9; 
                display: flex;align-items: center;justify-content: center;">
                    <div class="img_box"
                        style="border-radius: .25rem;width: 99%;height: 99%;overflow: hidden;display: flex;align-items: center;justify-content: center;position: relative;">
                        <video :src="item" controls></video>
                    </div>
                </div>
            </template>
            <div v-if="list.length < max || fileType == 'video'" class="w-1/5 lg:w-1/6" :style="{ width }" style="aspect-ratio: 1;border-radius: .25rem;cursor: pointer;
                     display: flex;align-items: center;justify-content: center;overflow: hidden;">
                <div style="width: 95%;height: 95%;border-radius: .25rem;border:.0625rem dashed #ccc; position: relative;
                     display: flex;align-items: center;justify-content: center;overflow: hidden;" @click="slectFile">
                    <span style="font-size: 60px;font-weight: 200;color: #999;padding-bottom: 10px;">+</span>
                    <div style="position: absolute;top: 0;right: 0;left: 0;bottom: 0;
                        background: rgba(0, 0, 0, .8);z-index: 99;display: flex;
                        justify-content: center;align-items: center;" class="text-xl font-bold text-primary"
                        v-if="showPercent">
                        {{ progress }}%
                    </div>
                </div>

            </div>
        </div>
    </div>
</template>

<style>
.mask {
    opacity: 0;
    transition: 500ms;
}

.img_box:hover .mask {
    opacity: 1;
}
</style>